package cn.dj.basic.interceptor;

import cn.dj.basic.jwt.JwtUtils;
import cn.dj.basic.jwt.LoginData;
import cn.dj.basic.jwt.Payload;
import cn.dj.basic.jwt.RsaUtils;
import io.jsonwebtoken.ExpiredJwtException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.security.PublicKey;
import java.util.concurrent.TimeUnit;

/**
 * 后端请求拦截器【拦截处理器controller的】
 */
//将该类交给Spring去管理 - 创建代理对象
@Component
public class LoginInterceptor implements HandlerInterceptor { //拦截所有请求:/**
   @Autowired//注入
   private RedisTemplate redisTemplate;

    /**
     * 到达处理器controller之前执行
     * @param request
     * @param response
     * @param handler
     * @return
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //获取请求头中的token
        String token = request.getHeader("token");//已经是jwtToken了 //main.js的axios前置拦截器处写的名字
        if (token!=null){
            //用jwt了
             try {
                 //解密之后获取登陆信息【因为用的私钥加密】
                 //获取公钥
                 PublicKey publicKey = RsaUtils.getPublicKey(RsaUtils.class.getClassLoader().getResource("auth_rsa.pub").getFile());
                 //解密 - 只要解密出来，不报错，就说明有。所以不用接收对象【该对象是当前登录人的信息】
               JwtUtils.getInfoFromToken(token, publicKey, LoginData.class);
                //放行
                 return true;//注意：没有刷新过期时间(30分钟过期-强制退出)
             } catch (ExpiredJwtException e) {
                 response.setContentType("application/json;charset=utf-8");
                 //重定向到登录界面
                 response.getWriter().println(" {\"success\":false,\"msg\":\"timeout\"}");//返回写出给页面信息 - 告知过期了，让前端页面跳转到登录页面
                 return false;//不会走controller了 - 拦截
            }

            //不再用下方redis形式了 - 改成jwt，redis中就没有存放登录信息了，所以根据token拿不到obj，所以为null - false - 拦截了
            //获取redis的登录信息
            //在logininfoImpl中存储的：token是key，value是登录信息logininfo对象 - 存到redis中
            //obj就是登录信息logininfo对象
        /*没有登录过，token就是null，如果不加判断，会报key为null的500错误
        根据null取redis获取value，就报这个错误。*/
//            Object obj = redisTemplate.opsForValue().get(token);//token已经是一个字符串了,所以不用加""
           /* //判断
            if (obj!=null){//登录过，还没有过期 - 还存在登录信息【过期时间从没有操作开始起算才对 - 所以要刷新重置过期时间】
                //刷新过期时间 - 只有还在操作，就要刷新
                //刷新过期时间
                redisTemplate.opsForValue().set(token,obj,30, TimeUnit.MINUTES);//每次操作之后，登录之后，要刷新一下过期时间-重写设置
                return  true;//放行
            }*/
        }
      //如果token等于null-没有登录过，就拦截
        //跳转到登录页面 - 后端跳不了，因为后端项目没有页面 - 放在前端跳转
        //最终目的是要调转到登录页面：响应json数据给前端，让前端判断去跳转
        //告诉浏览器，我响应了一个json数据给你，编码是utf-8。浏览器接收之后会自动转换成json对象
        response.setContentType("application/json;charset=utf-8");
          //重定向到登录界面
        response.getWriter().println(" {\"success\":false,\"msg\":\"noLogin\"}");//返回写出给页面信息，让前端页面跳转到登录页面
        return false;//不会走controller了 - 拦截

    }
}
